/**
 * app.js v1.2
 * 这是一个基于app的移动端UI框架
 * 作者：徐竣豪
 * 日期：2025年6月16日
 */

// 自定义tap事件
(function () {
  let touchStartTime = 0;
  let touchStartX = 0;
  let touchStartY = 0;

  document.addEventListener(
    "touchstart",
    function (e) {
      touchStartTime = Date.now();
      touchStartX = e.touches[0].clientX;
      touchStartY = e.touches[0].clientY;
    },
    { passive: true }
  );

  document.addEventListener(
    "touchend",
    function (e) {
      const timeDiff = Date.now() - touchStartTime;
      const xDiff = Math.abs(e.changedTouches[0].clientX - touchStartX);
      const yDiff = Math.abs(e.changedTouches[0].clientY - touchStartY);

      if (timeDiff < 300 && xDiff < 10 && yDiff < 10) {
        const tapEvent = new CustomEvent("tap", {
          bubbles: true,
          cancelable: true,
          detail: e,
        });
        e.target.dispatchEvent(tapEvent);
      }
    },
    { passive: true }
  );
})();

//app核心对象
const app = {
  // 在app对象中添加初始化方法
  init(config) {
    this.config = {
      autoInit: true,
      debug: false,
      ...config,
    };

    // 自动初始化密码切换组件
    this.passwordToggle.init(document);
    //自动初始化开关组件
    this.switch.init(document);

    if (this.config.refresh) {
      // 动态创建组件结构
      if (this.config.refresh.pullRefresh) {
        const refreshHtml = `
    <div class="app-pull-refresh">
      <div class="refresh-content">
        <div class="refresh-spinner"></div>
        <div class="refresh-text"></div>
      </div>
    </div>
  `;
        this.config.refresh.container
          .querySelector(".app-scroller")
          .insertAdjacentHTML("afterbegin", refreshHtml);
      }

      if (this.config.refresh.pullLoad) {
        const loadHtml = `
    <div class="app-pull-load">
      <div class="load-content">
        <div class="load-spinner"></div>
        <div class="load-text"></div>
      </div>
    </div>
  `;
        this.config.refresh.container.insertAdjacentHTML("beforeend", loadHtml);
      }
    }

    if (this.config.autoInit) {
      document.querySelectorAll("[data-app-init]").forEach((el) => {
        const component = el.dataset.appInit;

        if (this[component] && typeof this[component].init === "function") {
          this[component].init(el);
        }
      });
    }
  },

  mask: {
    el: null,
    create() {
      if (!this.el) {
        this.el = document.querySelector(".app-mask");
        if (!this.el) {
          this.el = document.createElement("div");
          this.el.className = "app-mask";
          document.body.appendChild(this.el);
        }
        this.bindEvents();
      }
      return this.el;
    },
    bindEvents() {
      this.el.addEventListener("tap", () => this.hide());
    },
    show() {
      const el = this.create();
      if (!el) return;

      document.body.style.overflow = "hidden";
      el.classList.remove("hide");
      el.style.display = "block";
      setTimeout(() => {
        el.classList.add("show");
        el.style.transform = "translateY(0)";
          el.dispatchEvent(new CustomEvent('maskChange', {
            bubbles: true,
            cancelable: true,
            detail: { visible: true }
          }));
      }, 10);
    },
    hide() {
      document.body.style.overflow = "";
      this.pop = this.pop || app.pop; // 添加兜底逻辑
      if(this.pop.el){
        this.pop.hide();
      }
      this.el.classList.add("hide");
      this.el.style.transform = "translateY(100%)";
      let timer = setTimeout(() => {
        this.el.classList.remove("show", "hide");
        this.el.style.display = "none";
        
        this.el.dispatchEvent(new CustomEvent('maskChange', {
          bubbles: true,
          cancelable: true,
          detail: { visible: false }
        }));
        clearTimeout(timer);
      }, 300);
    },
  },
  pop: {
    el: null,
    create() {
      if (!this.el) {
        this.el = document.querySelector(".app-pop");
        if (!this.el) {
          console.error("找不到静态定义的.app-pop元素");
          return null;
        }
      }
      return this.el;
    },
    show() {
      if (this.isAnimating) return;
      const el = this.create();
      if (!el) return;

      this.isAnimating = true;
      document.body.style.overflow = "hidden";
      this.mask = this.mask || app.mask;
      this.mask.show();
      el.classList.remove("hide");
      el.style.display = "block";

      clearTimeout(this.showTimer);
      this.showTimer = setTimeout(() => {
        el.classList.add("show");
        el.style.transform = "translateY(0)";
        this.isAnimating = false;
      }, 10);
    },
    hide() {
      if (this.isAnimating) return;
      this.isAnimating = true;

      document.body.style.overflow = "";
      this.mask.el.classList.add("hide");
      this.el.style.transform = "translateY(100%)";

      clearTimeout(this.hideTimer);
      this.hideTimer = setTimeout(() => {
        this.mask.hide();
        this.el.classList.remove("show", "hide");
        this.el.style.display = "none";
        this.isAnimating = false;
        clearTimeout(this.hideTimer);
      }, 300);
    },
  },

  /**
   * 发送AJAX请求的核心方法
   * @param {Object} options - 请求配置
   * @param {string} [options.method='GET'] - 请求方法
   * @param {string} options.url - 请求地址
   * @param {Object} [options.data] - 请求数据
   * @param {Object} [options.headers] - 请求头
   * @param {number} [options.timeout=0] - 超时时间(毫秒)
   * @returns {Promise} 返回Promise对象
   */
  ajax: function (options = {}) {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      xhr.timeout = options.timeout || 0;

      // 处理请求方法
      const method = (options.method || "GET").toUpperCase();
      let url = options.url;

      // 处理查询参数
      if (options.data && method === "GET") {
        const params = new URLSearchParams(options.data);
        url += (url.includes("?") ? "&" : "?") + params;
      }

      xhr.open(method, url);

      // 设置请求头
      if (options.headers) {
        Object.entries(options.headers).forEach(([key, value]) => {
          xhr.setRequestHeader(key, value);
        });
      }

      // 设置响应类型
      if (options.dataType === "json") {
        xhr.setRequestHeader("Accept", "application/json");
      }

      xhr.onload = () => {
        if (xhr.status >= 200 && xhr.status < 300) {
          let response = xhr.response;
          if (options.dataType === "json") {
            try {
              response = JSON.parse(response);
            } catch (e) {
              options.error && options.error(xhr, "parsererror", e);
              return reject(e);
            }
          }
          options.success && options.success(response, xhr.statusText, xhr);
          resolve(response);
        } else {
          options.error && options.error(xhr, "error", "Request failed");
          reject(new Error("Request failed"));
        }
      };

      xhr.onerror = () => {
        options.error && options.error(xhr, "error", "Network Error");
        reject(new Error("Network Error"));
      };

      xhr.ontimeout = () => {
        options.error && options.error(xhr, "timeout", "Request timeout");
        reject(new Error("Request timeout"));
      };

      // 发送请求体数据
      let data = options.data;
      if (data && method !== "GET") {
        if (options.contentType === "application/json") {
          xhr.setRequestHeader("Content-Type", "application/json");
          data = JSON.stringify(data);
        } else {
          xhr.setRequestHeader(
            "Content-Type",
            "application/x-www-form-urlencoded"
          );
          data = new URLSearchParams(data).toString();
        }
      }

      xhr.send(data);
    });
  },

  // 保留原有方法并改为使用新ajax实现
  get(url, data) {
    return this.ajax({
      method: "GET",
      url: url,
      data: data,
    });
  },

  getJson(url, data) {
    return this.ajax({
      method: "GET",
      url: url,
      data: data,
      dataType: "json",
    });
  },

  post(url, data) {
    return this.ajax({
      method: "POST",
      url: url,
      data: data,
    });
  },

  postJson(url, data) {
    return this.ajax({
      method: "POST",
      url: url,
      data: data,
      dataType: "json",
    });
  },
};

// 滚动条组件
app.scroll = {
  init(container) {
    this.items = container.querySelectorAll(".app-scroll-item");
    this.items.forEach((item) => {
      item.addEventListener("tap", () => {
        this.items.forEach((i) => i.classList.remove("app-active"));
        item.classList.add("app-active");

        // 获取元素属性
        const itemId = item.id;
        const customData = item.dataset.id;

        // 触发自定义事件
        const event = new CustomEvent("scrollItemClick", {
          detail: {
            target: item,
            id: itemId,
            dataset: item.dataset,
          },
        });
        container.dispatchEvent(event);
      });
    });
  },
};

// 密码切换组件
app.passwordToggle = {
  init(container) {
    const toggles = container.querySelectorAll(".app-password-toggle");
    if (toggles) {
      toggles.forEach((toggle) => {
        toggle.addEventListener("tap", function () {
          const wrapper = this.closest(".app-password-wrapper");
          const input = wrapper.querySelector("input");
          if (input.type === "password") {
            input.type = "text";
            this.classList.add("show-password");
          } else {
            input.type = "password";
            this.classList.remove("show-password");
          }
        });
      });
    }
  },
};

// 在app对象中添加轮播图方法
app.carousel = {
  // 保留原有方法
  // 在init方法中添加指示器生成逻辑
  init(container, options = {}) {
    this.container = container;
    this.items = container.querySelectorAll(".carousel-item"); // 确保先获取items
    this.currentIndex = 0;
    this.setupTouchEvents(container);

    // 合并默认配置
    this.options = {
      autoPlay: true,
      interval: 5000,
      loop: true, // 新增循环配置
      ...options,
    };

    if (this.options.autoPlay) {
      this.startAutoPlay();
    }

    // 动态生成指示器
    const indicatorContainer = this.container.querySelector(
      ".carousel-indicators"
    );
    const fragment = document.createDocumentFragment();
    this.items.forEach((_, index) => {
      const indicator = document.createElement("div");
      indicator.className = `carousel-indicator ${
        index === 0 ? "app-active" : ""
      }`;
      fragment.appendChild(indicator);
    });
    indicatorContainer.appendChild(fragment);
  },

  // 修改后的自动播放方法
  startAutoPlay() {
    this.interval = setInterval(() => {
      this.next();
    }, this.options.interval);
  },

  // 新增停止自动播放方法
  stopAutoPlay() {
    clearInterval(this.interval);
  },
  setupTouchEvents(container) {
    let startX = 0;
    container.addEventListener("touchstart", (e) => {
      startX = e.touches[0].clientX;
    });

    container.addEventListener("touchend", (e) => {
      const diff = startX - e.changedTouches[0].clientX;
      if (Math.abs(diff) > 30) {
        diff > 0 ? this.next() : this.prev();
      }
    });
  },
  // 修改后
  startAutoPlay() {
    this.interval = setInterval(() => {
      this.next();
    }, 5000);
  },

  // 补充next和prev方法实现
  next() {
    if (!this.items || this.items.length === 0) return;
    if (this.options.loop) {
      this.currentIndex = (this.currentIndex + 1) % this.items.length;
    } else {
      this.currentIndex = Math.min(
        this.currentIndex + 1,
        this.items.length - 1
      );
    }
    this.updateCarousel();
  },

  prev() {
    if (this.options.loop) {
      this.currentIndex =
        (this.currentIndex - 1 + this.items.length) % this.items.length;
    } else {
      this.currentIndex = Math.max(this.currentIndex - 1, 0);
    }
    this.updateCarousel();
  },

  updateCarousel() {
    this.items.forEach((item, index) => {
      item.style.transform = `translateX(${
        (index - this.currentIndex) * 100
      }%)`;
    });

    // 更新指示器状态
    const indicators = this.container.querySelectorAll(".carousel-indicator");
    indicators.forEach((indicator, index) => {
      indicator.classList.toggle("app-active", index === this.currentIndex);
    });
  },
};

// 上拉加载与下拉刷新组件
app.pullRefresh = {
  isRefreshing: false,

  init(container, options) {
    this.options = {
      onRefresh: () => {},
      onLoadMore: () => {},
      ...options,
    };
    this.container = container;
    this.scroller = container.querySelector(".app-scroller");
    this.loader = container.querySelector(".app-pull-load");
    this.loadText = container.querySelector(".load-text");
    this.refreshEl = container.querySelector(".app-pull-refresh");
    if (this.refreshEl) {
      this.refreshText = this.refreshEl.querySelector(".refresh-text");
    }
    this.setupPullEvents();
  },

  // 保留整合后的最新setupPullEvents方法（L434-459）
  setupPullEvents() {
    // 下拉刷新事件监听
    let startY = 0,
      validPull = false;

    this.scroller.addEventListener("touchstart", (e) => {
      if (!this.isRefreshing && this.scroller.scrollTop === 0) {
        if (this.refreshEl) {
          startY = e.touches[0].pageY;
          validPull = true;
          this.refreshEl.style.transition = "none"; // 拖动时禁用过渡效果
          this.refreshText.textContent = "下拉刷新";
        }
      }
    });

    // 完善下拉刷新触发逻辑
    this.scroller.addEventListener("touchend", (e) => {
      if (validPull && !this.isRefreshing) {
        if (this.refreshEl) {
          const computedStyle = getComputedStyle(this.refreshEl);
          const matrix = new DOMMatrix(computedStyle.transform);
          const currentY = matrix.m42; // 直接获取Y轴位移值

          if (currentY >= 100) {
            this.triggerRefresh();
            // 调用用户自定义回调
            // this.options.onRefresh(() => {
            //   this.endPullRefresh(true);
            // });
          } else {
            this.refreshEl.style.transition = "transform 0.3s ease";
            this.refreshEl.style.transform = "translateY(0)";
          }
          validPull = false;
        }
      }
    });

    this.scroller.addEventListener("touchmove", (e) => {
      if (validPull) {
        const deltaY = e.touches[0].pageY - startY;
        if (deltaY > 0) {
          this.refreshEl.style.transform = `translateY(${Math.min(
            deltaY * 0.6,
            150
          )}px)`;
        }
      }

      if (
        this.loader &&
        !this.isLoading &&
        this.scroller.scrollTop + this.scroller.clientHeight >=
          this.scroller.scrollHeight - 100
      ) {
        const deltaY = e.touches[0].pageY - startY;
        if (deltaY < -50) {
          this.triggerLoadMore();
          this.isLoading = true;
        }
      }
    });

    // 修改现有加载方法
  },

  // 在pullRefresh对象中新增公共方法
  endPullRefresh(success) {
    if (!this.refreshEl || !this.refreshText) return;

    this.refreshText.textContent = success ? "刷新完成" : "刷新失败";
    // this.refreshEl.style.transition =
    //   "transform 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94)";
    // this.refreshEl.style.transform = "translateY(-100%)";

    this.refreshEl.style.transform = "translateY(0)";
    this.isRefreshing = false;
    // setTimeout(() => {
    //   this.refreshEl.style.transform = "translateY(0)";
    //   this.isRefreshing = false;
    // }, 800);
  },

  endPullLoad(success) {
    if (!this.loader || !this.loadText) return;

    this.loadText.textContent = success ? "加载完成" : "加载更多数据";
    setTimeout(
      () => {
        this.loader.style.display = "none";
        this.isLoading = false;
      },
      success ? 1000 : 1500
    );
  },

  // 修改原有触发方法
  async triggerRefresh() {
    this.isRefreshing = true;
    this.refreshText.textContent = "释放刷新执行";
    this.refreshEl.style.display = "block";
    // this.refreshEl.style.transform = "translateY(0)";

    // 保留原有动画初始化逻辑
    this.options.onRefresh();
  },

  async triggerLoadMore() {
    if (this.isLoading) return;
    this.isLoading = true;
    this.loader.style.display = "block";
    this.loadText.textContent = "加载中...";

    this.options.onLoadMore();
  },
};

// 提示框
app.toast = function (message, options = {}) {
  // 创建Toast元素
  const toast = document.createElement("div");
  toast.className = "app-toast";
  toast.innerHTML = message;

  // 应用自定义类名
  if (options.className) {
    toast.classList.add(options.className);
  }

  // 设置位置（默认为底部）
  const position = options.position || "bottom";
  toast.classList.add(position);

  // 添加到body
  document.body.appendChild(toast);

  // 显示Toast
  setTimeout(() => {
    toast.classList.add("show");
  }, 10);

  // 自动移除
  setTimeout(() => {
    toast.style.opacity = "0";
    toast.style.transform = `translateX(-50%) ${
      position === "top" ? "translateY(-20px)" : "translateY(20px)"
    }`;

    // 动画结束后移除元素
    setTimeout(() => {
      if (toast.parentNode) {
        toast.parentNode.removeChild(toast);
      }
    }, 500);
  }, options.duration || 2000);
};

// 开关组件
app.switch = {
  init(container) {
    const switches = container.querySelectorAll(".app-switch");
    if (switches) {
      switches.forEach((sw) => {
        const input = sw.querySelector('input[type="checkbox"]');
        sw.addEventListener("tap", (e) => {
          e.stopImmediatePropagation();
          const newState = !input.checked;

          // 同步DOM属性
          input.setAttribute("checked", newState ? "" : null);

          // 先触发框架事件再触发原生事件
          sw.dispatchEvent(
            new CustomEvent("switchChange", {
              detail: { checked: newState },
            })
          );
        });
      });
    }
  },
};
